package com.itbaizhan.listener;
/*Filter与Listener设计模式
“知其然，知其所以然”。

Filter的设计模式
在Servlet的Filter中使用的责任链设计模式。

责任链模式特点

责任链（Chain of Responsibility）：责任链模式也叫职责链模式，
是一种对象行为模式。在责任链模式里，很多对象由每一个对象对其下一个对象的
引用而连接起来形成一条链。请求在这个链上传递，直到链上的某一个对象决定处理
此请求。发出这个请求的客户端并不需要知道链上的哪一个对象最终处理这个请求，
这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。

责任链的优缺点
优点：
降低了对象之间的耦合度。
增强了系统的可扩展性。
增强了给对象指派职责的灵活性。
责任链简化了对象之间的连接。
责任分担。每个类只需要处理自己该处理的工作。

缺点：
不能保证请求一定被接收。
对比较长的责任链，请求的处理可能涉及多个处理对象，系统性能将受到一定影响。
可能会由于责任链的错误设置而导致系统出错，如可能会造成循环调用。
Listener的设计模式
在Servlet的Listener中使用的观察者设计模式。

观察者模式的特点
观察者模式（Observer Pattern）：观察者模式是一种对象行为模式。
它定义对象间的一种一对多的依赖关系，当一个对象的状态发生改变时，
所有依赖于它的对象都得到通知并被自动更新。

观察者模式的优缺点
优点：
观察者和被观察者是抽象耦合的。
建立一套触发机制。

缺点：
如果一个被观察者对象有很多的直接和间接的观察者的话，将所有的观察者都通知到会花费很多时间。
如果在观察者和观察目标之间有循环依赖的话，观察目标会触发它们之间进行循环调用，可能导致系统崩溃。
观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的，而仅仅只是知道观察目标发生了变化。
*/

/*Listener监听器*/
/*监听器用于监听web应用中某些对象的创建、销毁、增加，修改，删除等动作的发生，
然后作出相应的响应处理。当范围对象的状态发生变化的时候，
服务器会自动调用监听器对象中的方法。

监听器分类
按监听的对象划分，可以分为：

ServletContext对象生命周期监听器(ServletContextListener接口)与属性操作监听器（ServletContextAttributeListener接口）;
HttpSession对象生命周期监听器(HttpSessionListener接口)与属性操作监听器（HttpSessionAttributeListener接口）;
ServletRequest对象生命周期监听器（ServletRequestListener接口）与属性操作监听器（ServletRequestAttributeListener接口）;*/
public class TestListener {
    /*ServletContext对象的生命周期监听器
ServletContextListener接口定义了ServletContext对象生命周期的监听行为。

void contextInitialized(ServletContextEvent sce)
ServletContext对象创建之后会触发该监听方法，并将ServletContext对象传递到该方法中。

void contextDestroyed(ServletContextEvent sce)
ServletContext对象在销毁之前会触发该监听方法，并将ServletContext对象传递到该方法中。*/
}
/*ServletContext对象的属性操作监听器
ServletContextAttributeListener接口定义了对于ServletContext对象属性操作的监听行为。


void attributeAdded(ServletContextAttributeEvent scae)
向ServletContext对象中添加属性时会触发该监听方法，并将
ServletContext对象传递到该方法中。
触发事件的方法servletContext.setAttribute("key","value")。

void attributeRemoved(ServletContextAttributeEvent scae)
当从ServletContext对象中删除属性时会触发该监听方法，并将
ServletContext对象传递到该方法中。触发事件
方法servletContext.removeAttribute("key")。


void attributeReplaced(ServletContextAttributeEvent scae)
当从ServletContext对象中属性的值发生替换时会触发该监听方法，
并将ServletContext对象传递到该方法中。触发事件的方法
servletContext.setAttribute("key","value")。*/

/*HttpSessionListener接口定义了HttpSession对象生命周期的监听行为。

void sessionCreated(HttpSessionEvent se)
HttpSession对象创建后会触发该监听方法，并将已创建HttpSession对象
传递到该方法中。


void sessionDestroyed(HttpSessionEvent se)
HttpSession对象在销毁之前会触发该监听方法，
并将要销毁的HttpSession对象传递到该方法中。*/

/*HttpSession对象的属性操作监听器
HttpSessionAttributeListener接口定义了对于HttpSession对象属性
操作的监听行为。

void attributeAdded(HttpSessionBindingEvent se)
向HttpSession对象中添加属性时会触发该监听方法，
并将HttpSession对象传递到该方法中。触发事件的方法
HttpSession.setAttribute("key","value")。

void attributeRemoved(HttpSessionBindingEvent se)
当从HttpSession对象中删除属性时会触发该监听方法，
并将HttpSession对象传递到该方法中。
触发事件方法HttpSession.removeAttribute("key")。

void attributeReplaced(HttpSessionBindingEvent se)
当从HttpSession对象中属性的值发生替换时会触发该监听方法，
并将HttpSession对象传递到该方法中。触发事件的方法
HttpSession.setAttribute("key","value")。*/

/*HttpServletRequest对象的生命周期监听器
ServletRequestListener接口定义了ServletRequest
(是HttpServletRequest接口的父接口类型)对象生命周期的监听行为。
（因为这里的ServletRequest接口不只是Http协议使用，其它的协议也使用，所以是
ServletRequest接口）

void requestInitialized(ServletRequestEvent sre)
HttpServletRequest对象创建后会触发该监听方法，、
并将已创建HttpServletRequest对象传递到该方法中。
（反回的是ServletRequest 不是HttpServletRequest 所以要强转为HttpServletRequest
  ）

void requestDestroyed(ServletRequestEvent sre)
HttpServletRequest对象在销毁之前会触发该监听方法，
并将要销毁HttpServletRequest对象传递到该方法中。*/

/*HttpServletRequest对象的属性操作监听器
ServletRequestAttributeListener接口定义了对于HttpServletRequest
对象属性操作的监听行为。


void attributeAdded(ServletRequestAttributeEvent srae)
向HttpServletRequest对象中添加属性时会触发该监听方法，
并将HttpServletRequest对象传递到该方法中。
触发事件的方法HttpServletRequest.setAttribute("key","value")。



void attributeRemoved(ServletRequestAttributeEvent srae)
当从HttpServletRequest对象中删除属性时会触发该监听方法，
并将HttpServletRequest对象传递到该方法中。
触发事件方法HttpServletRequest.removeAttribute("key")。



void attributeReplaced(ServletRequestAttributeEvent srae)
当从HttpServletRequest对象中属性的值发生替换时会触发该监听方法，并将HttpServletRequest对象传递到该方法中。
触发事件的方法HttpServletRequest.setAttribute("key","value")。*/



/*一、setAttribute()方法
作用：增加一个指定名称和值的新属性，或者把一个现有属性设定为指定的值。

语法：setAttribute(name，value)

说明：

（1）name：要设置的属性名

（2）value：要设置的属性值

注意：把指定的属性设置为指定的值。如果不存在具有指定名称的属性，该方法将创建一个新属性。

二、request.setAttribute()
作用：request.setAttribute()是在一次请求内共享数据

解释：例如将一个数据保存request域中，然后请求转发至前端页面，则数据转发至前端页面后会被自动销毁。简单点说就是，数据只能用一次就不能用了。

request.setAttribute("login_msg","验证码错误！");
request.getRequestDispatcher("/login.jsp").forward(request,response);
三、session.setAttribute()
作用：session.setAttribute()是在一次会话的多次请求之间共享数据

解释：而如果使用session.setAttribute()方法，则数据会被保存至整个会话结束。简单点说就是，数据只要不被销毁，就能一直用。

HttpSession session = request.getSession();
session.setAttribute("user",loginUser);
response.sendRedirect(request.getContextPath()+"/index.jsp");
注意：Session数据只能保存20分钟，当关闭浏览器时也会被销毁。
———————*/